TypeScript 98.3%
CSS 0.9%
Shell 0.7%
1// Carte des concepts : nœuds (avec maîtrise) + liens typés + compteurs de ressources.2import { NextResponse } from "next/server";3import { apiError, requireEnrollment } from "@/lib/api.ts";4import { requireUser } from "@/lib/auth/session.ts";5import { all } from "@/lib/db/index.ts";6import { masteryForCourse } from "@/lib/learning/mastery.ts";7import { normalizeCourse } from "@/lib/learning/helpers.ts";89export async function GET(_req: Request, ctx: { params: Promise<{ course: string }> }) {10 try {11 const user = await requireUser();12 const course = normalizeCourse((await ctx.params).course);13 requireEnrollment(user.id, course);1415 const mastery = new Map(masteryForCourse(user.id, course).map((m) => [m.conceptId, m]));16 const concepts = all<{ id: number; slug: string; name: string; description: string; week: number | null; importance: number; axis: string }>(17 "SELECT id, slug, name, description, week, importance, axis FROM concepts WHERE course_code = ? ORDER BY week, id",18 course19 );20 const counts = new Map<number, { cards: number; questions: number }>();21 for (const r of all<{ concept_id: number; n: number }>(22 "SELECT concept_id, COUNT(*) as n FROM flashcards WHERE course_code = ? AND concept_id IS NOT NULL GROUP BY concept_id", course23 )) counts.set(r.concept_id, { cards: r.n, questions: 0 });24 for (const r of all<{ concept_id: number; n: number }>(25 "SELECT concept_id, COUNT(*) as n FROM quiz_questions WHERE course_code = ? AND concept_id IS NOT NULL GROUP BY concept_id", course26 )) {27 const e = counts.get(r.concept_id) ?? { cards: 0, questions: 0 };28 e.questions = r.n;29 counts.set(r.concept_id, e);30 }3132 const ids = concepts.map((c) => c.id);33 const links = ids.length34 ? all<{ from_id: number; to_id: number; type: string }>(35 `SELECT from_id, to_id, type FROM concept_links WHERE from_id IN (${ids.map(() => "?").join(",")}) OR to_id IN (${ids.map(() => "?").join(",")})`,36 ...ids, ...ids37 )38 : [];3940 return NextResponse.json({41 nodes: concepts.map((c) => ({42 ...c,43 mastery: mastery.get(c.id)?.score ?? 0,44 level: mastery.get(c.id)?.level ?? "a-decouvrir",45 observations: mastery.get(c.id)?.observations ?? 0,46 cards: counts.get(c.id)?.cards ?? 0,47 questions: counts.get(c.id)?.questions ?? 0,48 })),49 links,50 });51 } catch (e) {52 return apiError(e);53 }54}55